<?php

require_once(APPLICATION_PATH . '/classes/reserveItem.class.php');
require_once(APPLICATION_PATH . '/classes/physicalCopy.class.php');
//require_once(APPLICATION_PATH . '/lib/Rd/Pdo.php'); #TODO dperecate, this was only needed pre 2.0
//Rd_Pdo::autoload();

class Rd_Synchronizer_ItemPhysicalCopies {
	
	protected $_item = NULL;
	protected $_internalCopies = NULL;
	protected $_ilsCopies = NULL;
	
	protected $_outOfSyncInternalCopies = array();
	protected $_missingIlsCopies = array();
	protected $_unsyncableCopies = array();
	protected $_purgableCopies = array();
	
	public function __construct($item)
	{
		$this->_item = 
			is_a($item,'item')
			? $item
			: new item($item);
	}
	
	public static function isSyncable($physicalCopy)
	{
		return 
			is_a($physicalCopy,'physicalCopy')
			&& '' != $physicalCopy->getBarcode() 
			&& !$physicalCopy->getOwnerUserID();
	}
	
	public function isSynced()
	{
		$this->_outOfSyncInternalCopies = array();
		$this->_missingIlsCopies = array();
		$this->_unsyncableCopies = array();
		$this->_purgableCopies = array();
		$internalPhysicalCopies = $this->getInternalCopies();
		$syncableCopies = array();
		foreach($internalPhysicalCopies as $physicalCopy) {
			if (self::isSyncable($physicalCopy)) {
				$syncableCopies[$physicalCopy->getId()] = $physicalCopy;
			} else {
				$this->_unsyncableCopies[$physicalCopy->getId()] = $physicalCopy;
			}
		}
		$ils = Rd_Registry::get('root:ils');
		$ilsCopies = $this->getIlsCopies();
		$itemsInSync = count($ilsCopies) == count($syncableCopies); 
		foreach($syncableCopies as $physicalCopy) {
			$itemMatched = FALSE;
			$itemInSync = FALSE;
			foreach($ilsCopies as $ilsKey => $ilsCopy) {
				if ($physicalCopy->getBarcode() == $ilsCopy['bar']) {
					$itemMatched = $ilsKey;
					break;
				}
			}
			if ($itemMatched !== FALSE) {
				$shelvingKey = $ils->getShelvingKey(
					$physicalCopy->getBarcode(),
					Rd_Ils::ITEM_CONTROL_KEY
				);
				$itemInSync = 
					$physicalCopy->getCallNumber() == $ilsCopies[$ilsKey]['callNum']
					&& $physicalCopy->getStatus() == $ilsCopies[$ilsKey]['loc']
					&& $physicalCopy->getOwningLibrary() == $ilsCopies[$ilsKey]['library']
					&& $physicalCopy->getItemType() == $ilsCopies[$ilsKey]['type']
					&& $physicalCopy->getShelvingKey() == $shelvingKey;
				if (!$itemInSync) {
					$itemsInSync = FALSE;
					$this->_outOfSyncInternalCopies[$physicalCopy->getId()] = $physicalCopy;
				}
			} else {
				$this->_purgableCopies[$physicalCopy->getId()] = $physicalCopy;
				$itemsInSync = FALSE;
			}
		}
		foreach($ilsCopies as $ilsKey => $ilsCopy) {
			$found = false;
			foreach($syncableCopies as $physicalCopy) {
				if($physicalCopy->getBarcode() == $ilsCopy['bar']) {
					$found = true;
					break;
				}
			}
			if (!$found) {
				$this->_missingIlsCopies[$ilsCopy['bar']] = $ilsCopy;
			}
		}
		return $itemsInSync;
	}
	
	public function syncAll($purgeMismatched = FALSE)
	{
		if(!$this->isSynced())
		{
			$ils = Rd_Registry::get('root:ils');
			foreach($this->_outOfSyncInternalCopies as $physicalCopy)
			{
				$barcode = $physicalCopy->getBarcode();
				$matchingIlsItem = NULL;
				foreach($this->_ilsCopies as $ilsCopy) {
					if($ilsCopy['bar'] == $barcode) {
						$matchingIlsItem = $ilsCopy;
						break;
					}
				}
				if (!is_null($ilsCopy)) {
					$physicalCopy->setCallNumber($ilsCopy['callNum']);
					$newKey = $ils->getShelvingKey($barcode,Rd_Ils::ITEM_CONTROL_KEY);
					$physicalCopy->setShelvingKey($newKey);
					$physicalCopy->setStatus($ilsCopy['loc']);
					$physicalCopy->setItemType($ilsCopy['type']);
					$physicalCopy->setOwningLibrary($ilsCopy['library']);
				}
			}
			foreach($this->_missingIlsCopies as $missingCopy){
				$newCopy = new physicalCopy();
				$newCopy->createPhysicalCopy();
				$newCopy->setItemID($this->_item->getId());
				$newCopy->setCallNumber($missingCopy['callNum']);
				$newCopy->setBarcode($missingCopy['bar']);
				$newCopy->setShelvingKey($ils->getShelvingKey($missingCopy['bar'], Rd_Ils::ITEM_CONTROL_KEY));
				$newCopy->setStatus($missingCopy['loc']);
				$newCopy->setItemType($missingCopy['type']);
				$newCopy->setOwningLibrary($missingCopy['library']);
			}
		}
		if ($purgeMismatched) {
			//Rd_Debug::out('purging ' . count($this->_purgableCopies) . ' copies');
			foreach($this->_purgableCopies as $purgableCopy) {
				$purgableCopy->destroy();
			}
		}
	}
	
	public function getInternalCopies($force = FALSE)
	{
		if($force || is_null($this->_internalCopies)) {
			$this->_internalCopies = $this->_item->getPhysicalCopies();
		}
		return $this->_internalCopies;
	}
	
	public function getIlsCopies($force = FALSE)
	{
		if ($force || is_null($this->_ilsCopies)) {
			$ils = Rd_Registry::get('root:ils');
			if (
				'' != $this->_item->getControlNumber()
			) {
				$this->_ilsCopies = $ils->getHoldings($this->_item->getControlNumber(), Rd_Ils::TITLE_CONTROL_KEY);
			} else {
				$this->_ilsCopies = array();
			}
		}
		return $this->_ilsCopies;
	}
	
	public function getOutOfSyncCopies()
	{
		return $this->_outOfSyncInternalCopies;
	}
	
	public function getUnsyncableCopies()
	{
		return $this->_unsyncableCopies;
	}
	
	public function getMissingIlsCopies()
	{
		return $this->_missingIlsCopies;
	}
	
	public function getPurgableCopies()
	{
		return $this->_purgableCopies;
	}
	
}